#include <cstring>
#include <cstdlib>
#include <string>
#include <map>

#include "GPSdata.hpp"
#include "GPSsplitter.hpp"

using namespace ModuleData;

// 
// 每种gps语句都是由一个语句类型加上这个类型相应的字段来组成的
// 
// 如: $GPRMC,063227.001,A,2232.1740,N,11401.1918,E,0.0,113.3,180806,,,A*6A
//     那么类型就是GPS_SENTENCE_GPRMC
//     具有的字段有:
//          UTC时间: 063227
//          定位状态: A
//          经度:    2232.1740,N
//          纬度:    11401.1918,E
//          地面速率: 0.0
//          地面航向: 113.3
//          UTC日期: 180806
//          磁偏角:  空
//          磁偏角方向: 空
//          定位模式: A
// 

typedef int AttrFmt[2];

struct gps_attr_fmt
{
  int                   attr_count;  // 这个GPS sentence有多少个属性
  AttrFmt              *attr_format; // 这个GPS每个属性的格式，下标0是属性的标识常量，1是属性占的长
  bool                  auto_active; // GPS的这个语句是否本来就是有效的
  int                   actived_idx; // “有效”字段的下标
  const char*           actived_val; // “有效”的时候字段的值
};

#include "gps_attribute.tab"

// 传入的data_str格式是"$xxxx,xxxx,xxxx,xxxx*xx"
bool GPSsplitter::operator() (const char* data_str, GPSdata *data)
{
  // 主要流程：
  // 1 取得消息的类型
  // 2 根据类型查表，得到到底需要如何进行截断数据
  // 3 将截断得到的数据传给obj_creator得到一个类对象的指针
  // 4 将数据加入到GPSdata中

  // 1
  int  msg_type;
  char buffer[ 64 ];

  int data_len = strlen( data_str );
  int scanned_pos;
  // 1-1 取得第一段
  for( scanned_pos=0; data_str[ scanned_pos ] != '$'; ++scanned_pos )
    {
    }
  for ( scanned_pos=0; scanned_pos < data_len && data_str[ scanned_pos ] != ','; ++scanned_pos )
    {
      buffer[ scanned_pos ] = data_str[ scanned_pos ];
    }
  buffer[ scanned_pos++ ] = '\0';

  // 1-2 查看消息类型
  for ( msg_type = 0; msg_type < GPS_SENTENCE_MAX; ++msg_type )
    {
      if ( 0 == strcmp( buffer, sentence_type[ msg_type ] ) )
	{
	  break;
	}
    }

  // 1-3 填写消息类型
  if ( msg_type < GPS_SENTENCE_MAX )
    {
      data->set_type( msg_type );
    }
  else
    {
      return false;
    }


  // step 2 & 3 & 4
  gps_attr_fmt &cur = all_sentence[ msg_type ];
  if ( cur.attr_format != NULL ) { // 可以控制的消息
    AttrFmt *fmt_table = &cur.attr_format[0];

    for ( int current_attr = 0; current_attr < cur.attr_count && scanned_pos < data_len; ++current_attr )
      {
	char *p = buffer;
	for ( int scanned_block = 0; scanned_pos < data_len;)
	  {
	    if ( data_str[ scanned_pos ] == ',' ) // 完成一个block
	      {
		++scanned_block;
		if ( scanned_block < fmt_table[ current_attr ][1] ) {
		  *p++ = data_str[ scanned_pos++ ];
		}
		else {
		  ++scanned_pos;
		  break;
		}
	      }
	    else if ( data_str[ scanned_pos ] == '*')
	      {
		break;
	      }
	    else
	      {
		*p++ = data_str[ scanned_pos++ ];
	      }
	  }
	*p = '\0';

	data->set_value( fmt_table[ current_attr ][ 0 ], 
			 buffer );

	if ( !cur.auto_active )
	  {
	    if ( current_attr == cur.actived_idx && 0 == strcmp( buffer, cur.actived_val) ){
	      data->set_avaiable( );
	    }
	  }

      }

    if ( cur.auto_active )
      {
	data->set_avaiable( );
      }

    return true;
  }
  else 
    {
      return false;
    }
}
